home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / atc / update.c < prev   
Encoding:
C/C++ Source or Header  |  1995-05-03  |  9.8 KB  |  411 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Ed James.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. /*
  38.  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
  39.  *
  40.  * Copy permission is hereby granted provided that this notice is
  41.  * retained on all partial or complete copies.
  42.  *
  43.  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
  44.  */
  45.  
  46. #ifndef lint
  47. static char sccsid[] = "@(#)update.c    5.5 (Berkeley) 10/30/90";
  48. #endif not lint
  49.  
  50. #include "include.h"
  51.  
  52. update()
  53. {
  54.     int    i, dir_diff, mask, unclean;
  55.     PLANE    *pp, *p1, *p2, *p;
  56.  
  57. #ifdef BSD
  58.     mask = sigblock(sigmask(SIGINT));
  59. #endif
  60. #ifdef SYSV
  61.     alarm(0);
  62.     signal(SIGALRM, update);
  63. #endif
  64.  
  65.     clck++;
  66.  
  67.     erase_all();
  68.  
  69.     /* put some planes in the air */
  70.     do {
  71.         unclean = 0;
  72.         for (pp = ground.head; pp != NULL; pp = pp->next) {
  73.             if (pp->new_altitude > 0) {
  74.                 delete(&ground, pp);
  75.                 append(&air, pp);
  76.                 unclean = 1;
  77.                 break;
  78.             }
  79.         }
  80.     } while (unclean);
  81.  
  82.     /* do altitude change and basic movement */
  83.     for (pp = air.head; pp != NULL; pp = pp->next) {
  84.         /* type 0 only move every other turn */
  85.         if (pp->plane_type == 0 && clck & 1)
  86.             continue;
  87.  
  88.         pp->fuel--;
  89.         if (pp->fuel < 0)
  90.             loser(pp, "ran out of fuel.");
  91.  
  92.         pp->altitude += SGN(pp->new_altitude - pp->altitude);
  93.  
  94.         if (!pp->delayd) {
  95.             dir_diff = pp->new_dir - pp->dir;
  96.             /*
  97.              * Allow for circle commands
  98.              */
  99.             if (pp->new_dir >= 0 && pp->new_dir < MAXDIR) {
  100.                 if (dir_diff > MAXDIR/2)
  101.                     dir_diff -= MAXDIR;
  102.                 else if (dir_diff < -(MAXDIR/2))
  103.                     dir_diff += MAXDIR;
  104.             }
  105.             if (dir_diff > 2)
  106.                 dir_diff = 2;
  107.             else if (dir_diff < -2)
  108.                 dir_diff = -2;
  109.             pp->dir += dir_diff;
  110.             if (pp->dir >= MAXDIR)
  111.                 pp->dir -= MAXDIR;
  112.             else if (pp->dir < 0)
  113.                 pp->dir += MAXDIR;
  114.         }
  115.         pp->xpos += displacement[pp->dir].dx;
  116.         pp->ypos += displacement[pp->dir].dy;
  117.  
  118.         if (pp->delayd && pp->xpos == sp->beacon[pp->delayd_no].x &&
  119.             pp->ypos == sp->beacon[pp->delayd_no].y) {
  120.             pp->delayd = 0;
  121.             if (pp->status == S_UNMARKED)
  122.                 pp->status = S_MARKED;
  123.         }
  124.  
  125.         switch (pp->dest_type) {
  126.         case T_AIRPORT:
  127.             if (pp->xpos == sp->airport[pp->dest_no].x &&
  128.                 pp->ypos == sp->airport[pp->dest_no].y &&
  129.                 pp->altitude == 0) {
  130.                 if (pp->dir != sp->airport[pp->dest_no].dir)
  131.                     loser(pp, "landed in the wrong direction.");
  132.                 else {
  133.                     pp->status = S_GONE;
  134.                     continue;
  135.                 }
  136.             }
  137.             break;
  138.         case T_EXIT:
  139.             if (pp->xpos == sp->exit[pp->dest_no].x &&
  140.                 pp->ypos == sp->exit[pp->dest_no].y) {
  141.                     if (pp->altitude != 9)
  142.                     loser(pp, "exited at the wrong altitude.");
  143.                 else {
  144.                     pp->status = S_GONE;
  145.                     continue;
  146.                 }
  147.             }
  148.             break;
  149.         default:
  150.             loser(pp, "has a bizarre destination, get help!");
  151.         }
  152.         if (pp->altitude > 9)
  153.             /* "this is impossible" */
  154.             loser(pp, "exceded flight ceiling.");
  155.         if (pp->altitude <= 0) {
  156.             for (i = 0; i < sp->num_airports; i++)
  157.                 if (pp->xpos == sp->airport[i].x &&
  158.                     pp->ypos == sp->airport[i].y) {
  159.                     if (pp->dest_type == T_AIRPORT)
  160.                         loser(pp, 
  161.                         "landed at the wrong airport.");
  162.                     else
  163.                         loser(pp, 
  164.                         "landed instead of exited.");
  165.                 }
  166.             loser(pp, "crashed on the ground.");
  167.         }
  168.         if (pp->xpos < 1 || pp->xpos >= sp->width - 1 ||
  169.             pp->ypos < 1 || pp->ypos >= sp->height - 1) {
  170.             for (i = 0; i < sp->num_exits; i++)
  171.                 if (pp->xpos == sp->exit[i].x &&
  172.                     pp->ypos == sp->exit[i].y) {
  173.                     if (pp->dest_type == T_EXIT)
  174.                         loser(pp, 
  175.                         "exited via the wrong exit.");
  176.                     else
  177.                         loser(pp, 
  178.                         "exited instead of landed.");
  179.                 }
  180.             loser(pp, "illegally left the flight arena.");
  181.         }
  182.     }
  183.  
  184.     /*
  185.      * Traverse the list once, deleting the planes that are gone.
  186.      */
  187.     for (pp = air.head; pp != NULL; pp = p2) {
  188.         p2 = pp->next;
  189.         if (pp->status == S_GONE) {
  190.             safe_planes++;
  191.             delete(&air, pp);
  192.         }
  193.     }
  194.  
  195.     draw_all();
  196.  
  197.     for (p1 = air.head; p1 != NULL; p1 = p1->next)
  198.         for (p2 = p1->next; p2 != NULL; p2 = p2->next)
  199.             if (too_close(p1, p2, 1)) {
  200.                 static char    buf[80];
  201.  
  202.                 (void)sprintf(buf, "collided with plane '%c'.",
  203.                     name(p2));
  204.                 loser(p1, buf);
  205.             }
  206.     /*
  207.      * Check every other update.  Actually, only add on even updates.
  208.      * Otherwise, prop jobs show up *on* entrance.  Remember that
  209.      * we don't update props on odd updates.
  210.      */
  211.     if ((rand() % sp->newplane_time) == 0)
  212.         addplane();
  213.  
  214. #ifdef BSD
  215.     sigsetmask(mask);
  216. #endif
  217. #ifdef SYSV
  218.     alarm(sp->update_secs);
  219. #endif
  220. }
  221.  
  222. char *
  223. command(pp)
  224.     PLANE    *pp;
  225. {
  226.     static char    buf[50], *bp, *comm_start;
  227.     char    *index();
  228.  
  229.     buf[0] = '\0';
  230.     bp = buf;
  231.     (void)sprintf(bp, "%c%d%c%c%d: ", name(pp), pp->altitude, 
  232.         (pp->fuel < LOWFUEL) ? '*' : ' ',
  233.         (pp->dest_type == T_AIRPORT) ? 'A' : 'E', pp->dest_no);
  234.  
  235.     comm_start = bp = index(buf, '\0');
  236.     if (pp->altitude == 0)
  237.         (void)sprintf(bp, "Holding @ A%d", pp->orig_no);
  238.     else if (pp->new_dir >= MAXDIR || pp->new_dir < 0)
  239.         strcpy(bp, "Circle");
  240.     else if (pp->new_dir != pp->dir)
  241.         (void)sprintf(bp, "%d", dir_deg(pp->new_dir));
  242.  
  243.     bp = index(buf, '\0');
  244.     if (pp->delayd)
  245.         (void)sprintf(bp, " @ B%d", pp->delayd_no);
  246.  
  247.     bp = index(buf, '\0');
  248.     if (*comm_start == '\0' && 
  249.         (pp->status == S_UNMARKED || pp->status == S_IGNORED))
  250.         strcpy(bp, "---------");
  251.     return (buf);
  252. }
  253.  
  254. /* char */
  255. name(p)
  256.     PLANE    *p;
  257. {
  258.     if (p->plane_type == 0)
  259.         return ('A' + p->plane_no);
  260.     else
  261.         return ('a' + p->plane_no);
  262. }
  263.  
  264. number(l)
  265. {
  266.     if (l < 'a' && l > 'z' && l < 'A' && l > 'Z')
  267.         return (-1);
  268.     else if (l >= 'a' && l <= 'z')
  269.         return (l - 'a');
  270.     else 
  271.         return (l - 'A');
  272. }
  273.  
  274. next_plane()
  275. {
  276.     static int    last_plane = -1;
  277.     PLANE        *pp;
  278.     int        found, start_plane = last_plane;
  279.  
  280.     do {
  281.         found = 0;
  282.         last_plane++;
  283.         if (last_plane >= 26)
  284.             last_plane = 0;
  285.         for (pp = air.head; pp != NULL; pp = pp->next)
  286.             if (pp->plane_no == last_plane) {
  287.                 found++;
  288.                 break;
  289.             }
  290.         if (!found)
  291.             for (pp = ground.head; pp != NULL; pp = pp->next)
  292.                 if (pp->plane_no == last_plane) {
  293.                     found++;
  294.                     break;
  295.                 }
  296.     } while (found && last_plane != start_plane);
  297.     if (last_plane == start_plane)
  298.         return (-1);
  299.     return (last_plane);
  300. }
  301.  
  302. addplane()
  303. {
  304.     PLANE    p, *pp, *p1;
  305.     int    i, num_starts, close, rnd, rnd2, pnum;
  306.  
  307.     bzero(&p, sizeof (p));
  308.  
  309.     p.status = S_MARKED;
  310.     p.plane_type = random() % 2;
  311.  
  312.     num_starts = sp->num_exits + sp->num_airports;
  313.     rnd = random() % num_starts;
  314.  
  315.     if (rnd < sp->num_exits) {
  316.         p.dest_type = T_EXIT;
  317.         p.dest_no = rnd;
  318.     } else {
  319.         p.dest_type = T_AIRPORT;
  320.         p.dest_no = rnd - sp->num_exits;
  321.     }
  322.  
  323.     /* loop until we get a plane not near another */
  324.     for (i = 0; i < num_starts; i++) {
  325.         /* loop till we get a different start point */
  326.         while ((rnd2 = random() % num_starts) == rnd)
  327.             ;
  328.         if (rnd2 < sp->num_exits) {
  329.             p.orig_type = T_EXIT;
  330.             p.orig_no = rnd2;
  331.             p.xpos = sp->exit[rnd2].x;
  332.             p.ypos = sp->exit[rnd2].y;
  333.             p.new_dir = p.dir = sp->exit[rnd2].dir;
  334.             p.altitude = p.new_altitude = 7;
  335.             close = 0;
  336.             for (p1 = air.head; p1 != NULL; p1 = p1->next)
  337.                 if (too_close(p1, &p, 4)) {
  338.                     close++;
  339.                     break;
  340.                 }
  341.             if (close)
  342.                 continue;
  343.         } else {
  344.             p.orig_type = T_AIRPORT;
  345.             p.orig_no = rnd2 - sp->num_exits;
  346.             p.xpos = sp->airport[p.orig_no].x;
  347.             p.ypos = sp->airport[p.orig_no].y;
  348.             p.new_dir = p.dir = sp->airport[p.orig_no].dir;
  349.             p.altitude = p.new_altitude = 0;
  350.         }
  351.         p.fuel = sp->width + sp->height;
  352.         break;
  353.     }
  354.     if (i >= num_starts)
  355.         return (-1);
  356.     pnum = next_plane();
  357.     if (pnum < 0)
  358.         return (-1);
  359.     p.plane_no = pnum;
  360.  
  361.     pp = newplane();
  362.     bcopy(&p, pp, sizeof (p));
  363.  
  364.     if (pp->orig_type == T_AIRPORT)
  365.         append(&ground, pp);
  366.     else
  367.         append(&air, pp);
  368.  
  369.     return (pp->dest_type);
  370. }
  371.  
  372. PLANE    *
  373. findplane(n)
  374. {
  375.     PLANE    *pp;
  376.  
  377.     for (pp = air.head; pp != NULL; pp = pp->next)
  378.         if (pp->plane_no == n)
  379.             return (pp);
  380.     for (pp = ground.head; pp != NULL; pp = pp->next)
  381.         if (pp->plane_no == n)
  382.             return (pp);
  383.     return (NULL);
  384. }
  385.  
  386. too_close(p1, p2, dist)
  387.     PLANE    *p1, *p2;
  388. {
  389.     if (ABS(p1->altitude - p2->altitude) <= dist &&
  390.         ABS(p1->xpos - p2->xpos) <= dist && ABS(p1->ypos - p2->ypos) <= dist)
  391.         return (1);
  392.     else
  393.         return (0);
  394. }
  395.  
  396. dir_deg(d)
  397. {
  398.     switch (d) {
  399.     case 0: return (0);
  400.     case 1: return (45);
  401.     case 2: return (90);
  402.     case 3: return (135);
  403.     case 4: return (180);
  404.     case 5: return (225);
  405.     case 6: return (270);
  406.     case 7: return (315);
  407.     default:
  408.         return (-1);
  409.     }
  410. }
  411.